import { getExpandedRowModel } from '@tanstack/react-table';
import cx from 'classnames';
import React, { useContext, useEffect, useMemo, useState } from 'react';

import DisplayTable from '.';
import CheckBox from '../../../Checkbox';
import { prefix } from '../../../config';
import Modal from '../../../Modal';
import { DownArrowIcon } from '../../../Svg';
import { deepClone, getPrefixCls } from '../../../utils';
import { defaultColumns } from '../../config';
import TableContext, { createContext, UPDATE_NAME } from '../../context/table';
import { getColumn } from '../../utils';

import { SETTING_MODAL } from '../../config';
import * as utils from '../../utils';

import type { CellContext, ExpandedState } from '@tanstack/react-table';
import type { ModalProps } from '../../../Modal';
import type { Context } from '../../context/table';
import type {
  AnyObject,
  Column,
  ColumnMeta,
  DisplayTableProps,
  TableMeta,
} from '../../type';

export type ColumnConfig = {
  id: string;
  title?: any;
  isShow?: boolean;
  isSummary?: boolean;
  isCanSummary?: boolean; // 是否禁用合计
  subRows?: ColumnConfig[];
};
export type SettingCheckBoxInfo = { [key in string]: boolean };
export interface ConfirmData {
  columnVisibility: SettingCheckBoxInfo;
  columnSummary: SettingCheckBoxInfo;
}
export interface Props<T extends AnyObject, Context = any> extends ModalProps {
  id?: string;
  isShowSummary?: boolean;
  columns: Column<T>[];
  columnVisibility: SettingCheckBoxInfo;
  columnSummary: SettingCheckBoxInfo;
  context?: React.Context<Context>;
  onConfirm?: ({ columnVisibility }: ConfirmData) => void;
  onCancel?: () => void;
}

const prefixCls = getPrefixCls(prefix.editableTable, 'setting-modal');
const columnNamePrefixCls = getPrefixCls(prefixCls, 'column-name');

function SettingCheckbox<T extends AnyObject>({
  info,
  update,
  disabled,
}: {
  disabled?: boolean;
  info: CellContext<T, unknown>;
  update: (id: string, value: boolean) => void;
}) {
  const { getValue, row } = info;

  const initialValue = getValue() as boolean;
  const [value, setValue] = useState(initialValue);

  React.useEffect(() => {
    setValue(initialValue);
  }, [initialValue]);
  return (
    <CheckBox
      disabled={disabled}
      checked={value}
      onChange={(e) => {
        const value = e.target.checked;
        setValue(value);
        update(row.original.id, value);
      }}
    />
  );
}

function SettingModal<T extends AnyObject>(props: Props<T>) {
  const {
    columnVisibility,
    columnSummary,
    columns: displayTableColumns,
    visible,
    isShowSummary,
    context,
    id,
    ...restProps
  } = props;
  const { table: tableContextInfo, dispatch } = useContext<Context<T>>(context);

  const allColumns = useMemo(
    () =>
      displayTableColumns.filter(
        (column) => !defaultColumns.includes(column.id),
      ),
    [displayTableColumns, defaultColumns],
  );

  const deep = (columns: Column<T>[], result: ColumnConfig[] = []) => {
    columns.forEach((column: any) => {
      const columnMeta: ColumnMeta<T> = column.meta || {};
      const { dataKey } = columnMeta;
      const meta =
        ((dataKey && getColumn(dataKey, allColumns)) || column).meta || {};
      const { editType, dataType } = meta;
      const id = column.id;
      const isShow = !!columnVisibility[id];
      const isCanSummary = (editType || dataType) === 'number';
      const isSummary = columnSummary[id];
      const item: ColumnConfig = {
        id,
        title: column.header,
        isShow,
        isSummary,
        isCanSummary,
      };

      if (columnMeta.columns && columnMeta.columns.length) {
        if (!item.subRows) item.subRows = [];
        item.subRows = deep(columnMeta.columns, item.subRows);
      }
      result.push(item);
    });
    return result;
  };
  const getInitDataSource = () => deep(allColumns);
  const columns = useMemo(() => {
    const columns: Column<ColumnConfig>[] = [
      {
        id: 'title',
        header: '列名',
        cell: (info) => {
          const { row } = info;
          return (
            <div
              className={columnNamePrefixCls}
              style={{ paddingLeft: row.depth * 15 }}
            >
              <div className={`${columnNamePrefixCls}__text`}>
                {info.getValue() as React.ReactNode}
              </div>
              {!!row.subRows && !!row.subRows.length && (
                <div
                  className={cx(`${columnNamePrefixCls}__icon`, {
                    up: row.getIsExpanded(),
                  })}
                  onClick={row.getToggleExpandedHandler()}
                >
                  <DownArrowIcon />
                </div>
              )}
            </div>
          );
        },
      },
      {
        id: 'isShow',
        header: '显示',
        size: 80,
        meta: { align: 'center' },
        cell: (info) => {
          const { table } = info;
          const tableMeta = table.options.meta as TableMeta;

          return (
            <SettingCheckbox
              info={info}
              update={tableMeta.updateColumnVisivleData}
            />
          );
        },
      },
    ];
    if (isShowSummary)
      columns.push({
        id: 'isSummary',
        header: '合计',
        size: 80,
        meta: { align: 'center' },
        cell: (info) => {
          const { table, row } = info;
          const tableMeta = table.options.meta as TableMeta;

          return (
            <SettingCheckbox
              disabled={!row.original.isCanSummary}
              info={info}
              update={tableMeta.updateSummaryData}
            />
          );
        },
      });
    return columns;
  }, [isShowSummary]);

  const [expanded, setExpanded] = useState<ExpandedState>({});
  const [dataSource, setDataSource] =
    useState<ColumnConfig[]>(getInitDataSource);

  useEffect(() => {
    if (!tableContextInfo.name)
      dispatch({ type: UPDATE_NAME, payload: SETTING_MODAL });
  }, [tableContextInfo.name]);
  useEffect(() => {
    visible && setDataSource(getInitDataSource());
  }, [visible, columnVisibility, displayTableColumns]);

  // 更改 显示(isShow) 值
  const updateColumnVisivleData = (id: string, visible: boolean) => {
    const data: ColumnConfig[] = deepClone(dataSource);

    const change = (data: ColumnConfig[]) => {
      data.forEach((item) => {
        if (item.subRows && item.subRows.length)
          item.subRows = change(item.subRows);

        if (item.id === id) item.isShow = visible;
      });
      return data;
    };
    setDataSource(change(data));
  };
  // 更改 合并(isSummary) 值
  const updateSummaryData = (id: string, isSummary: boolean) => {
    const data: ColumnConfig[] = deepClone(dataSource);

    const change = (data: ColumnConfig[]) => {
      data.forEach((item) => {
        if (item.subRows && item.subRows.length)
          item.subRows = change(item.subRows);

        if (item.id === id) item.isSummary = isSummary;
      });
      return data;
    };
    setDataSource(change(data));
  };
  // 将dataSource 的 isShow 数据转换成 columnVisibility
  const transformData = (key: string, dataSource: ColumnConfig[]) => {
    const transformedData: { [key in string]: boolean } = {};
    const transform = (
      data: ColumnConfig[],
      result: SettingCheckBoxInfo = {},
    ) => {
      data.forEach((item) => {
        const { id } = item;
        transformedData[id] = item[key];
        if (item.subRows && item.subRows.length)
          transform(item.subRows, result);
      });
      return result;
    };
    return transform(dataSource, transformedData);
  };

  const reset = () => {
    setExpanded({});
    setDataSource(getInitDataSource());
  };
  const onConfirm = () => {
    const data = {
      columnVisibility: transformData('isShow', dataSource),
      columnSummary: transformData('isSummary', dataSource),
    };
    reset();
    props.onConfirm && props.onConfirm(data);
  };
  const onCancel = () => {
    reset();
    props.onCancel && props.onCancel();
  };

  const tableProps: DisplayTableProps<ColumnConfig> = {
    isCanSetting: false,
    isShowIndex: false,
    isShowSummary: false,
    isCanResizeColumn: false,
    bordered: false,
    id,
    context,
    columns,
    dataSource,
    tableOptions: {
      state: { expanded },
      getSubRows: (row) => row.subRows,
      getExpandedRowModel: getExpandedRowModel(),
      onExpandedChange: setExpanded,
      meta: { updateColumnVisivleData, updateSummaryData },
    },
  };

  const modalProps = {
    visible,
    width: 500,
    ...restProps,
  };
  return (
    <Modal
      destroyOnClose
      className={prefixCls}
      title="列设置"
      visible={visible}
      {...modalProps}
      onOk={onConfirm}
      onCancel={onCancel}
    >
      <div className={`${prefixCls}-content`}>
        <DisplayTable {...tableProps} />
      </div>
    </Modal>
  );
}

function SelectTableModalContext<T extends AnyObject>(props: Props<T>) {
  const { context, ...restProps } = props;
  const tableId = useMemo(
    () => props.id || utils.createTableId('table'),
    [props.id],
  );
  const tableContext = useMemo(() => createContext(), [tableId]);
  const tableProps = { ...restProps, id: tableId };
  if (context) {
    return <SettingModal {...tableProps} context={context} />;
  } else {
    return (
      <TableContext context={tableContext}>
        <SettingModal {...tableProps} context={tableContext} />
      </TableContext>
    );
  }
}
export default SelectTableModalContext;
